 
/* 
 * Copyright (C) Ignacio Lucas
 */
 
/*
 *  Librería que encpasula una cola FIFO
 *
 *  Ignacio Lucas <ignacio.lucas@gmail.com>
 *
 */
#include "common.h"
#include "queue.h"
#include "utils/object_pool.h"

// estructura que representa un nodo en la cola
typedef struct s_queue_node
{
		void *data;
		struct s_queue_node *next;
	
} queue_node;

// estructura que representa la cola.
typedef struct s_queue
{
		queue_node *node_head;
		queue_node *node_tail;
		int count;
		//int last_max_count;
	
} queue;

// tamanio de un nodo de la cola.
size_t queue_get_node_size()
{
	return sizeof(queue_node);
}


queue_t queue_create()
{
	queue *q;

	if ((q = (queue *)malloc(sizeof(queue))) == NULL)
	{
		return NULL;
	}
	q->node_head=NULL;
	q->node_tail=NULL;
	q->count=0;
	//q->last_max_count=0;
	return (queue_t)q;
}

int queue_push(queue_t qt, void *data)
{
	queue *q=(queue *)qt;
	queue_node *node=NULL;
	
	node = (queue_node *)common_objects_pool_get(QUEUE_POOL);
	if (node==NULL)
	{
		return 1;
	}
	node->data=data;
	node->next=NULL;
		
	if (q->node_head==NULL)
	{
		q->node_head=node;
		q->node_tail=node;
	}
	else
	{
		q->node_tail->next=node;
		// actualiza el elemento de la cola al ultimo elemento.
		q->node_tail=node;
	}
	q->count++;
	
	//if (q->last_max_count < q->count)
	//{
	//	q->last_max_count = q->count;
	//	logger_core_info( "[queue push] max_size=%d", q->last_max_count);
	//}
	
	return 0;
}

int queue_push_vector(queue_t q, void **data, int size)
{
	int i=0, total_push=0, ret=0;
	for (i=0; (i<size) && (ret == 0); i++)
	{
		ret=queue_push(q,data[i]);
		if (ret == 0)
		{
			total_push++;
		}
	}
	return total_push;
}

void* queue_pull(queue_t qt)
{
	queue *q=(queue *)qt;
	queue_node *node_head=q->node_head;
	void *ret=NULL;
	
	if (node_head == NULL)
	{
		return NULL;
	}
	ret=node_head->data;
	q->node_head=q->node_head->next;

	common_objects_pool_put(QUEUE_POOL, node_head);

	if (q->node_head == NULL)
	{
		q->node_tail=NULL;
	}
	q->count--;
	return ret;
}

int queue_is_empty(queue_t qt)
{
	return ((queue *)qt)->node_head == NULL;
}

int queue_destroy(queue_t q)
{
	queue * theq=(queue *)q;
	while (queue_pull(q) != NULL);
	
	free(theq);	
	return 0;
}
